package com.cqc;

import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.FieldValue;
import co.elastic.clients.elasticsearch._types.SortOrder;
import co.elastic.clients.elasticsearch._types.query_dsl.MatchQuery;
import co.elastic.clients.elasticsearch.core.*;
import co.elastic.clients.elasticsearch.core.bulk.BulkOperation;
import co.elastic.clients.elasticsearch.core.bulk.BulkResponseItem;
import co.elastic.clients.elasticsearch.core.search.Hit;
import co.elastic.clients.elasticsearch.core.search.HitsMetadata;
import co.elastic.clients.elasticsearch.indices.CreateIndexRequest;
import co.elastic.clients.elasticsearch.indices.CreateIndexResponse;
import co.elastic.clients.elasticsearch.indices.DeleteIndexResponse;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import co.elastic.clients.util.ObjectBuilder;
import com.cqc.pojo.Document;
import org.apache.commons.math3.stat.descriptive.summary.Product;
import org.elasticsearch.client.RestClient;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;

/**
 * @author cui
 * @date 2025/8/5 21:50
 * @description
 **/
@SpringBootTest
public class ElasticsearchClientTest {

    @Autowired
    ElasticsearchClient client;

    String index_book = "index_book";


    @AfterAll
    public static void close() throws IOException {

    }

    /**
     * 获取集群信息
     */
    @Test
    public void info() throws IOException {
        InfoResponse infoResponse = client.info();
        System.out.println(infoResponse);
    }

    @Test
    public void index() throws IOException {
        CreateIndexResponse createIndexResponse = client.indices()
                .create(builder -> builder
                        .index(index_book)
                        .mappings(m -> m
                                .properties("fileId", p -> p.keyword(k -> k))// fileId 用 keyword，精确匹配
                                .properties("fileName", p -> p
                                        .text(t -> t
                                                .analyzer("ik_max_word")
                                                .searchAnalyzer("ik_smart")))
                                .properties("content", p -> p
                                        .text(t -> t
                                                .analyzer("ik_max_word")//索引时使用 ik_max_word 分词器 (细粒度)
                                                .searchAnalyzer("ik_smart")))// 搜索时使用 ik_smart 分词器 (粗粒度，更精准)
                        )
                );
        System.out.println(createIndexResponse.acknowledged());
    }

    /**
     * 所以是否存在
     */
    @Test
    public void indexExist() throws IOException {
        boolean value = client.indices().exists(e -> e.index(index_book)).value();
        System.out.println(value);
    }


    /**
     * 所以不存在，就报错：  co.elastic.clients.elasticsearch._types.ElasticsearchException:
     * [es/indices.delete] failed: [index_not_found_exception] no such index [index_book]
     */
    @Test
    public void deleteIndex() throws IOException {
        DeleteIndexResponse response = client.indices()
                .delete(d -> d.index(index_book));
        System.out.println(response.acknowledged());
        System.out.println(response.toString());
    }

    @Test
    public void deleteDocument() throws IOException {
        DeleteResponse deleteResponse = client.delete(d -> d.index(index_book).id("AAAA03"));
        System.out.println(deleteResponse.toString());
    }

    /**
     * 添加文档
     */
    @Test
    public void addDocument() throws IOException {
        String fileId1 = "AAAA03";
        String fileName1 = "汴京残梦";
        String content1 = "《汴京残梦》是历史学家黄仁宇创作的长篇小说，2005年4月由新星出版社首次出版。该书以北宋徽宗宣和年间为背景，通过虚构人物徐承茵参与绘制《清明上河图》的经历，串联起花石纲运输、朝堂党争、靖康之变等历史事件 [2]。小说采用虚实结合手法，刻画蔡京、宋徽宗等真实历史人物，并通过徐承茵与柔福帝姬的情感线展现个人命运与时代洪流的交织。";
        Document document1 = new Document(fileId1, fileName1, content1);

        IndexResponse indexResponse = client.index(builder -> builder.index(index_book)
                .id(fileId1)
                .document(document1));

        System.out.println(indexResponse);
    }

    @Test
    public void updateDocument() throws IOException {
        String fileId1 = "AAAA01";
        String fileName1 = "万历十五年U2";
        String content1 = "《万历十五年》从“大历史观”的研究视角出发，选取了明朝万历十五年（1587年）作为考察切入点，运用历史小说的叙事模式和传记体式的章节，通过对关键历史人物悲惨命运的描述，探析了晚明帝国走向衰落的深刻原因。 [1]这充分体现了作者的大历史观，即宏观的、系统的历史，也即“从技术的角度看待历史”。";
        Document document1 = new Document(fileId1, fileName1, content1);

        //UpdateResponse<Document> updateResponse = client.update(u -> u
        //                .index(index_book)
        //                .id(fileId1)
        //                .doc(document1)
        //                .upsert(document1),
        //        Document.class
        //);
        //或者
        UpdateRequest<Document, Document> updateRequest = new UpdateRequest.Builder<Document, Document>()
                .index(index_book)
                .id(fileId1)
                .doc(document1)
                .upsert(document1)
                .build();
        UpdateResponse<Document> updateResponse = client.update(updateRequest, Document.class);
        System.out.println(updateResponse);
    }

    /**
     * +
     * 批量添加文档
     */
    @Test
    public void batchAddDocument() throws IOException {
        String fileId1 = "AAAA01";
        String fileName1 = "万历十五年";
        String content1 = "《万历十五年》从“大历史观”的研究视角出发，选取了明朝万历十五年（1587年）作为考察切入点，运用历史小说的叙事模式和传记体式的章节，通过对关键历史人物悲惨命运的描述，探析了晚明帝国走向衰落的深刻原因。 [1]这充分体现了作者的大历史观，即宏观的、系统的历史，也即“从技术的角度看待历史”。";
        Document document1 = new Document(fileId1, fileName1, content1);

        String fileId2 = "AAAA02";
        String fileName2 = "中国大历史";
        String content2 = "《中国大历史》是2007年由生活·读书·新知三联书店出版社出版的图书，作者是黄仁宇。 [1]该书是历史学家黄仁宇体现其“大历史观”的一部专著，它旁引了不少研究内容，分析中国历朝发展的问题，从欧洲的历史，以至经济学都有利用。";
        Document document2 = new Document(fileId2, fileName2, content2);

        List<Document> documentList = new ArrayList<>();
        documentList.add(document1);
        documentList.add(document2);

        BulkRequest.Builder builder = new BulkRequest.Builder();
        for (Document document : documentList) {
            builder.operations(idx ->
                    idx.index(indexOperation -> indexOperation.index(index_book)
                            .id(document.getFileId())
                            .document(document)
                    )
            );
        }
        BulkRequest bulkRequest = builder.build();
        BulkResponse bulkResponse = client.bulk(bulkRequest);
        boolean errorsFlag = bulkResponse.errors();
        if (errorsFlag) {
            List<BulkResponseItem> itemList = bulkResponse.items();
            for (BulkResponseItem item : itemList) {
                //System.out.println(item.toString());
                if (null != item.error()) {
                    System.out.println(item.error().reason());
                }
            }
        }
        System.out.println(bulkResponse);
    }

    @Test
    public void queryById() throws IOException {
        String id = "AAAA02";
        //GetRequest getRequest = GetRequest.of(b -> b.index(index_book).id(id));
        GetResponse<Document> getResponse = client.get(x -> x.index(index_book).id(id), Document.class);

        if (getResponse.found()) {
            Document document = getResponse.source();
            System.out.println(document.toString());
        } else {
            System.out.println("无数据");
        }
    }

    @Test
    public void query() throws IOException {
        SearchResponse<Document> searchResponse = client.search(s -> s.index(index_book)
                        .query(q -> q
                                .matchAll(m -> m))
                        .size(100),
                Document.class);

        List<Hit<Document>> hits = searchResponse.hits().hits();
        for (Hit<Document> hit : hits) {
            Document document = hit.source();
            System.out.println(document);
        }
    }

    @Test
    public void queryByCondition() throws IOException {
        SearchResponse<Document> searchResponse = client.search(s -> s.index(index_book)
                        .query(q -> q
                                .match(m -> m
                                        .field("content")
                                        .query(FieldValue.of("万历")))),//党争
                Document.class);

        List<Hit<Document>> hits = searchResponse.hits().hits();
        for (Hit<Document> hit : hits) {
            Document document = hit.source();
            System.out.println(document);
        }
    }

    @Test
    public void queryPage() throws IOException {
        SearchResponse<Document> searchResponse = client.search(s -> s.index(index_book)
                        .from(0)
                        .size(30)
                        .query(q -> q
                                .match(m -> m
                                        .field("content")
                                        .query(FieldValue.of("历史"))
                                )
                        )
                        .sort(so -> so
                                .field(f -> f
                                        .field("fileId")
                                        .order(SortOrder.Desc)
                                )
                        ),
                Document.class);

        HitsMetadata<Document> hitsMetadata = searchResponse.hits();
        long total = hitsMetadata.total().value();
        List<Hit<Document>> hits = hitsMetadata.hits();
        for (Hit<Document> hit : hits) {
            Document document = hit.source();
            System.out.println(document);
        }
    }
}
